package Model;

import java.util.Random;

/**
 * Potentially generates a random event for a player. Only called at the end of
 * each turn in the pub.
 * 
 * @author Philip Pecher
 * 
 */
public class RandomEvent {
	private static Random prng;
	private static final double[] factors = { .25, .25, .25, .50, .50, .50,
			.50, .75, .75, .75, .75, 1 };

	/**
	 * Constructor initializes the random number generator
	 */
	public RandomEvent() {
		if (RandomEvent.prng == null) {
			RandomEvent.prng = new Random();
		}
	}

	/**
	 * Determines whether a player will have an event triggered
	 * 
	 * @param currentPlayer
	 *            the player for which the event should occur
	 * @param players
	 *            all player objects that are currently partaking in the game
	 * @return a boolean of whether the event occurs
	 */
	public boolean eventOccurs(Player currentPlayer, Player[] players) {
		// currentPlayer is assumed to have the lowest score unless proven
		// otherwise
		// 'tell, dont ask' cannot be used as there is no container for the
		// players
		boolean hasLowestScore = true;
		for (Player p : players) {
			if (p.equals(currentPlayer))
				continue; // dont compare currentPlayer against itself
			if (p.getScore() < currentPlayer.getScore())
				hasLowestScore = false;
		}
		return (RandomEvent.prng.nextDouble() < .27 && !hasLowestScore) ? true
				: false;
	}

	/**
	 * Generates a random event and executes the instructions of that event
	 * against the provided player. Returns a string that details the exact
	 * changes to the given players resources.
	 * 
	 * @param roundCount
	 *            the current round number (used to scale the money change)
	 * @param currentPlayer
	 *            the player for which an event should be executed for
	 * @return a string of what event occurred and what resources were changed
	 */
	public String executeAndReturnEvent(int roundCount, Player currentPlayer) {
		double factor = factors[roundCount - 1];
		double cashChange = 0;
		// Violates interface injection because this is the only reference
		switch (RandomEvent.prng.nextInt(7)) {
		case 0:
			currentPlayer.setFood(currentPlayer.getFood() + 3);
			currentPlayer.setEnergy(currentPlayer.getEnergy() + 2);
			return "YOU JUST RECEIVED A PACKAGE FROM THE GT ALUMNI CONTAINING 3 FOOD AND 2 ENERGY UNITS.";
		case 1:
			currentPlayer.setOre(currentPlayer.getOre() + 2);
			return "A WANDERING TECH STUDENT REPAID YOUR HOSPITALITY BY LEAVING TWO BARS OF ORE.";
		case 2:
			cashChange = factor * 8000000;
			System.out.println("random event case 2: cashChange = "+cashChange);
			currentPlayer.setMoney(max(currentPlayer.getMoney() + (int) cashChange, 0));
			return "THE MUSEUM BOUGHT YOUR ANTIQUE PERSONAL COMPUTER FOR $ "
					+ (int) cashChange;
		case 3:
			cashChange = factor * 2000000;
			System.out.println("random event case 3: cashChange = "+cashChange);
			currentPlayer.setMoney(max(currentPlayer.getMoney() + (int) cashChange, 0));
			return "YOU FOUND A DEAD MOOSE RAT AND SOLD THE HIDE FOR $"
					+ (int) cashChange;
		case 4:
			cashChange = factor * 4000000;
			System.out.println("random event case 4: cashChange = "+cashChange);
			currentPlayer.setMoney(max(currentPlayer.getMoney() - (int) cashChange, 0));
			return "FLYING CAT-BUGS ATE THE ROOF OFF YOUR HOUSE. REPAIRS COST $"
					+ (int) cashChange;
		case 5:
			currentPlayer.setFood(currentPlayer.getFood() / 2);
			return "MISCHIEVOUS UGA STUDENTS BROKE INTO YOUR STORAGE SHED AND STOLE HALF YOUR FOOD.";
		case 6:
			cashChange = factor * 6000000;
			System.out.println("random event case 6: cashChange = "+cashChange);
			currentPlayer.setMoney(max(currentPlayer.getMoney() - (int) cashChange, 0));
			return "YOUR SPACE GYPSY INLAWS MADE A MESS OF THE TOWN. IT COST YOU $"
					+ (int) cashChange  + " TO CLEAN IT UP.";
		default:
			return "Error: You probably forgot to call the RandomEvent constructor.";
		}
	}
	
	/**
	 * Returns the greater of two ints
	 * @param a
	 * @param b
	 * @return the bigger int
	 */
	public int max(int a, int b)
	{
		if( a > b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}
	
	/**
	 * Returns the smaller of two ints
	 * @param a
	 * @param b
	 * @return the smaller int
	 */
	public int min(int a, int b)
	{
		if( a < b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}
}
